<script setup lang="ts">
import { ref } from 'vue'

// 创建一个响应式变量 article，用于存储后端返回的数据
const article = ref('')

// 定义一个 AbortController 对象，用于控制请求的中止
let abort: AbortController

// 建立 SSE 连接的函数
const connectSSE = async () => {
  // 创建一个新的 AbortController 对象
  abort = new AbortController()

  // 发送 POST 请求到 chat_typing_fetch 接口
  const res = await fetch('http://localhost:3000/chat_typing_fetch', {
    signal: abort.signal, // 请求中断标识
    method: 'POST', // POST 请求可以传输更多数据
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ user: 'itheima' })
  })

  // 获取响应的 ReadableStream 对象
  const content = res.body?.getReader()

  // 创建一个 TextDecoder 对象，用于将二进制数据转换为字符串
  const decode = new TextDecoder()

  // 循环读取数据
  while (content) {
    // done 是否已完成，value 后端返回的数据(二进制)
    const { done, value } = await content.read()

    if (done) {
      closeSSE() // 如果请求已经完成，中断连接
      break // 退出循环
    }

    // 将二进制数据转换为字符串，并存储到 article 变量中
    article.value += decode.decode(value)
  }
}

// 关闭 SSE 连接的函数
const closeSSE = () => {
  abort.abort()
}
</script>

<template>
  <h1>ChatGPT打字效果 - EventSource</h1>
  <button @click="connectSSE">建立 SSE 连接</button>
  <button @click="closeSSE">关闭 SSE 连接</button>
  <div class="box">
    {{ article }}
  </div>
</template>

<style scoped>
.box {
  width: 300px;
  height: 300px;
  background-color: pink;
  border: 1px solid #f00;
}
</style>
